import datetime
import io
import json
import time

import qrcode
import requests
from loguru import logger
from starlette.responses import StreamingResponse

from Util.EncoderUtil import encode, decode, getAuthToken
from config.Database import get_db
from schemas.Result import Result
from schemas.SignApplyInfo import SignApplyInfoCreate
from services.SignApplyInfoServe import SignApplyInfoServe
from services.UserService import UserServe
sign_apply_info_serve = SignApplyInfoServe()
UserServe = UserServe()

# 获取可以签到签退的活动列表
async def get_all_sign_activity(token):
    params = f'{{"pageNum":1,"pageSize":999,"applyStatus":"","status":"7,8","queryType":""}}'
    try:
        response = requests.get(
            "https://ekta.jjvu.jx.cn/api/app/client/v1/activity/my-list",
            params={"params": encode(params)},
            headers={"Authorization": encode(getAuthToken(token))}
        )

        decrypted_string = decode(response.text)
        if not decrypted_string:
            raise Exception("getDetail 解密结果为空字符串")

        decrypted_json = json.loads(decrypted_string)
        return {"data":decrypted_json['data'],"msg":decrypted_json['msg']}
    except Exception as e:
        logger.info(f"get_all_sign_activity 函数内部错误: {e}")
        return None

# 直接使用请求签到签退
async def sign_in_out(id, token, sign_type=2):
    # 先获得活动的详细信息 从详细信息里面获得管理员id
    detail = await get_detail(id, token)
    managerUserId = detail['manager']['id']
    if not managerUserId:
        return Result.fail(msg="获取管理员id失败")
    allUserInfo = await UserServe.get_user_info(token)



    timestamp = int(time.time() * 1000)
    params = f'{{"id":"{id}","userId":"{managerUserId}","type":"{sign_type}","sp":"{timestamp}"}}'

    try:
        response = requests.post(
            "https://ekta.jjvu.jx.cn/api/app/client/v1/activity/sign/in-out",
            params={"params": encode(params)},
            headers={"Authorization": encode(getAuthToken(token))}
        )

        decrypted_string = decode(response.text)
        if not decrypted_string:
            raise Exception("getDetail 解密结果为空字符串")

        decrypted_json = json.loads(decrypted_string)

        db = next(get_db())
        # 在这里插入数据库
        try:
            # 直接插入一条立即签到的记录
            # 在这里插入一条签到的记录
            if decrypted_json['code'] == 10002:
                success = 2
            else:
                success = 1
            sign_apply_info_serve.create(db, SignApplyInfoCreate(createAt=datetime.datetime.now(), remark=decrypted_json['msg'],
                                                                 activityId=str(detail['id']),activityName=detail['name'],nickName=allUserInfo['name'],
                                                                 username=allUserInfo['code'],signTime=datetime.datetime.now(),
                                                                signType=0,password="null",isApply=1,isSuccess=success))
        except Exception as e:
            logger.info(f"sign_in_out 插入数据报错函数内部错误: {e}")

        return {"data":decrypted_json['data'],"msg":decrypted_json['msg']}
    except Exception as e:
        logger.info(f"sign_in_out 函数内部错误: {e}")
        return None

# 获取活动签到签退码
async def get_sign_code(id, token):
    # 先获得活动的详细信息 从详细信息里面获得管理员id
    detail = await get_detail(id, token)
    managerUserId = detail['manager']['id']
    if not managerUserId:
        return Result.fail(msg="获取管理员id失败")
    timestamp = int(time.time() * 1000)
    params = f"qutuo://sign?activityId={id}&userId={managerUserId}&sp={timestamp}"
    # 构造签到二维码
    QRCode = encode(params) + '?yiban=yiban_scan_result'

    # 生成二维码
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=10,
        border=4,
    )
    qr.add_data(QRCode)
    qr.make(fit=True)

    img = qr.make_image(fill_color="black", back_color="white")
    # 将图像写入内存中的字节流
    buf = io.BytesIO()
    img.save(buf, format='PNG')
    buf.seek(0)
    # 返回二维码图片流
    return StreamingResponse(buf, media_type="image/png")

#获取活动公告
async def get_notice(id,token):
    params = f'{{"pageNum":1,"pageSize":999,"activityId":"{id}"}}'
    try:
        # 发起请求
        response = requests.get(
            "https://ekta.jjvu.jx.cn/api/app/client/v1/activity/noticeList",
            params={"params": encode(params)},
            headers={"Authorization": encode(getAuthToken(token))}
        )

        # 解密响应
        decrypted_string = decode(response.text)
        if not decrypted_string:
            raise Exception("getDetail 解密结果为空字符串")

        # 解析JSON
        decrypted_json = json.loads(decrypted_string)

        return decrypted_json["data"]

    except Exception as e:
        print(f"get_notice 函数内部错误: {e}")
        return None

# 获取活动详情
async def get_detail(id, token):
    page2 = f'{{"id":"{id}"}}'
    try:
        # 发起请求
        response = requests.get(
            "https://ekta.jjvu.jx.cn/api/app/client/v1/activity/detail/non-member",
            params={"params": encode(page2)},
            headers={"Authorization": encode(getAuthToken(token))}
        )

        # 解密响应
        decrypted_string = decode(response.text)
        if not decrypted_string:
            raise Exception("getDetail 解密结果为空字符串")

        # 解析JSON
        decrypted_json = json.loads(decrypted_string)

        return decrypted_json["data"]

    except Exception as e:
        print(f"getDetail 函数内部错误: {e}")
        return None

# 申请报名活动
async def apply_activity(id, token):
    params = f'{{"id":{id},"personMaterial":[]}}'
    encoded_params = encode(params)
    try:
        # 发起POST请求
        response = requests.post(
            "https://ekta.jjvu.jx.cn/api/app/client/v1/activity/enroll/person",
            data=f"params={encoded_params}",
            headers={
                "Authorization": encode(getAuthToken(token)),
                "Origin": "https://ekta.jjvu.jx.cn",
                "Referer": "https://ekta.jjvu.jx.cn",
                "Content-Type": "application/x-www-form-urlencoded",
                "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1"
            }
        )

        # 解密响应
        decrypted_string = decode(response.text)
        if not decrypted_string:
            raise Exception("applyActivity 解密结果为空字符串")

        # 解析JSON
        decrypted_json = json.loads(decrypted_string)

        if decrypted_json["data"] is None:
            logger.info('申请失败', decrypted_json["msg"])

        return decrypted_json

    except Exception as e:
        logger.info(f"applyActivity 函数内部错误: {e}")
        if hasattr(e, 'response'):
            logger.info(f"服务器响应: {e.response.status_code}, {e.response.text}")
        return None